<script setup>
import { onMounted, ref } from 'vue';
import { validCaptchaApi } from '@/apis/captcha'
import { useCaptchaStore } from '@/stores/captcha';
import { ElMessage, ElLoading } from 'element-plus'
//背景图片
const bgImg = ref(null);
//滑块图片
const sliderImg = ref(null);
//滑块移动按钮
const sliderMoveBtn = ref(null)
//滑块图片包裹
const sliderImgdiv = ref(null)
const captchaId = ref("");
const captchaStore = useCaptchaStore()
//验证码相关配置
let captchaConfig
//
const validSuccess = ref(false)


const emit = defineEmits(['get-status'])    //定义事件

const openFullScreen = () => {     //加载中
    const loading = ElLoading.service({
        lock: true,
        text: '主人，小小正在努力校验验证码中，请稍等',
        background: 'rgba(0, 0, 0, 0.7)',
    })
    setTimeout(() => {
        loading.close()
    }, 1000)
}

onMounted(() => {
    refresh()
})
const refresh = async () => {
    reset()                                 //重置滑块
    let data = await captchaStore.genCaptcha()     //请求获取验证码
    captchaId.value = data.id;              //验证码的id用于校验时
    bgImg.value.src = data.captcha.backgroundImage
    sliderImg.value.src = data.captcha.sliderImage
    captchaStore.initConfig(bgImg.value.width, bgImg.value.height, sliderImg.value.width, sliderImg.value.height, 206)
    //注意这里不能直接用后端生成的图片原始尺寸，因为前端的尺寸是经过压缩的，不然就会gg
    captchaConfig = captchaStore.captchaConfig      //赋值之后再获取配置信息
}

const reset = () => {
    sliderMoveBtn.value.style = "background-position:" + "-5px 11.79625%"
    sliderMoveBtn.value.style = "transform:" + "translate(0px, 0px)"
    sliderImgdiv.value.style = "transform:" + "translate(0px, 0px)"
    captchaId.value = null;
}
//鼠标或者手机按下
const down = (event) => {
    let targetTouches = event.originalEvent ? event.originalEvent.targetTouches : event.targetTouches;
    let startX = event.pageX;
    let startY = event.pageY;
    if (startX === undefined) {
        startX = Math.round(targetTouches[0].pageX);
        startY = Math.round(targetTouches[0].pageY);
    }
    captchaConfig.startX = startX;
    captchaConfig.startY = startY;

    const pageX = captchaConfig.startX;
    const pageY = captchaConfig.startY;
    const startTime = captchaConfig.startTime;
    const trackArr = captchaConfig.trackArr;
    trackArr.push({
        x: pageX - startX,
        y: pageY - startY,
        type: "down",
        t: (new Date().getTime() - startTime.getTime())
    });
    // pc
    window.addEventListener("mousemove", move);
    window.addEventListener("mouseup", up);
    // 手机端
    window.addEventListener("touchmove", move, false);
    window.addEventListener("touchend", up, false);
    doDown();
}

const doDown = () => {
    sliderMoveBtn.value.style = "background-position:" + "-5px 31.0092%"
}

const move = (event) => {
    if (event instanceof TouchEvent) {
        event = event.touches[0];
    }
    let pageX = Math.round(event.pageX);
    let pageY = Math.round(event.pageY);
    const startX = captchaConfig.startX;
    const startY = captchaConfig.startY;
    const startTime = captchaConfig.startTime;
    const end = captchaConfig.end;
    const bgImageWidth = captchaConfig.bgImageWidth;
    const trackArr = captchaConfig.trackArr;
    let moveX = pageX - startX;
    const track = {
        x: pageX - startX,
        y: pageY - startY,
        type: "move",
        t: (new Date().getTime() - startTime.getTime())
    };
    trackArr.push(track);
    if (moveX < 0) {
        moveX = 0;
    } else if (moveX > end) {
        moveX = end;
    }
    captchaConfig.moveX = moveX;
    captchaConfig.movePercent = moveX / bgImageWidth;
    doMove(captchaConfig);
}

const doMove = (captchaConfig) => {
    const moveX = captchaConfig.moveX;
    sliderMoveBtn.value.style = "transform:" + "translate(" + moveX + "px, 0px)"
    sliderImgdiv.value.style = "transform:" + "translate(" + moveX + "px, 0px)"
}

const up = (event) => {
    window.removeEventListener("mousemove", move);
    window.removeEventListener("mouseup", up);
    window.removeEventListener("touchmove", move);
    window.removeEventListener("touchend", up);
    if (event instanceof TouchEvent) {
        event = event.changedTouches[0];
    }
    captchaConfig.stopTime = new Date();
    let pageX = Math.round(event.pageX);
    let pageY = Math.round(event.pageY);
    const startX = captchaConfig.startX;
    const startY = captchaConfig.startY;
    const startTime = captchaConfig.startTime;
    const trackArr = captchaConfig.trackArr;

    const track = {
        x: pageX - startX,
        y: pageY - startY,
        type: "up",
        t: (new Date().getTime() - startTime.getTime())
    }
    trackArr.push(track);
    valid(captchaConfig);
}


const valid = async (captchaConfig) => {
    openFullScreen()
    let data = {
        bgImageWidth: captchaConfig.bgImageWidth,
        bgImageHeight: captchaConfig.bgImageHeight,
        sliderImageWidth: captchaConfig.sliderImageWidth,
        sliderImageHeight: captchaConfig.sliderImageHeight,
        startSlidingTime: captchaConfig.startTime,
        entSlidingTime: captchaConfig.stopTime,
        trackList: captchaConfig.trackArr
    };
    const res = await validCaptchaApi(captchaId.value, data)
    if (res) {
        validSuccess.value = true;
        emit('get-status', true)     //校验通过  通知父组件状态
        ElMessage.success("验证通过")
    } else {
        ElMessage.error("验证码校验失败，请重试")
        refresh()
    }
}
</script>

<template>
    <div class="slider">
        <div class="content">
            <div class="bg-img-div">
                <img ref="bgImg" alt />
            </div>
            <div class="slider-img-div" ref="sliderImgdiv">
                <img ref="sliderImg" style="background:none;" /> <!--因为导入了全局覆盖样式，所以这里需要修改-->
            </div>
        </div>
        <div class="slider-move">
            <div class="slider-move-track">
                拖动滑块完成拼图
            </div>
            <div class="slider-move-btn" ref="sliderMoveBtn" @mousedown="down" @touchstart="down">
            </div>
        </div>
        <div class="bottom">
            <div class="close-btn right" id="slider-close-btn"></div>
            <div class="refresh-btn right" @click.prevent="refresh"></div>
            <span class="pass-text right" v-if="validSuccess">验证通过,耗时0.{{captchaConfig.stopTime - captchaConfig.startTime}}s</span>
        </div>
    </div>
</template>



<style>
.slider {
    background-color: #fff;
    width: 278px;
    height: 285px;
    z-index: 999;
    box-sizing: border-box;
    padding: 9px;
    border-radius: 6px;
    box-shadow: 0 0 11px 0 #999999;
    margin: 0 auto;
}

.slider .content {
    width: 100%;
    height: 159px;
    position: relative;
}

.bg-img-div {
    width: 100%;
    height: 100%;
    position: absolute;
    transform: translate(0px, 0px);
}

.slider-img-div {
    height: 100%;
    position: absolute;
    transform: translate(0px, 0px);
}

.bg-img-div img {
    width: 100%;
}

.slider-img-div img {
    height: 100%;
}

.slider .slider-move {
    height: 60px;
    width: 100%;
    margin: 11px 0;
    position: relative;
}

.slider .bottom {
    height: 19px;
    width: 100%;
    display: flex;
    .right{
        margin-right: 10px;
    }
}

.refresh-btn,
.close-btn,
.slider-move-track,
.slider-move-btn {
    background: url(https://static.geetest.com/static/ant/sprite.1.2.4.png) no-repeat;
}

.refresh-btn,
.close-btn {
    display: inline-block;
}

.slider-move .slider-move-track {
    line-height: 38px;
    font-size: 14px;
    text-align: center;
    white-space: nowrap;
    color: #88949d;
    -moz-user-select: none;
    -webkit-user-select: none;
    user-select: none;
}

.slider {
    user-select: none;
}

.slider-move .slider-move-btn {
    transform: translate(0px, 0px);
    background-position: -5px 11.79625%;
    position: absolute;
    top: -12px;
    left: 0;
    width: 66px;
    height: 66px;
}

.slider-move-btn:hover,
.close-btn:hover,
.refresh-btn:hover {
    cursor: pointer
}

.bottom .close-btn {
    width: 20px;
    height: 20px;
    background-position: 0 44.86874%;
}

.bottom .refresh-btn {
    width: 20px;
    height: 20px;
    background-position: 0 81.38425%;
}

.pass-text {
    color: rgb(29, 157, 106);
}
</style>